package com.markerhub.controller;

import com.markerhub.common.lang.Result;
import com.markerhub.entity.CourseLearnUnit;
import com.markerhub.service.CourseLearnUnitService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;


@Slf4j
@RestController
@RequestMapping("/file")
public class FileController {
    @Autowired
    CourseLearnUnitService unitService;

    @Value("${file.upload.path}")
    private String uploadPath;

    @PostMapping("/upload/{unitId}")
    public Result uploadFile(
            @RequestParam("file") MultipartFile file,
            @PathVariable Integer unitId,
            @RequestParam("fileType") String fileType) {
        try {
            // 生成文件名
            String originalFilename = file.getOriginalFilename();
            String fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
            String fileName = UUID.randomUUID().toString() + fileExtension;
            // 创建单元目录和文件类型目录
            String unitPath = String.format("%s/unit_%d/%s", uploadPath, unitId, fileType);
            File directory = new File(unitPath);
            if (!directory.exists()) {
                directory.mkdirs();
            }
            // 保存文件
            File dest = new File(directory.getPath() + "/" + fileName);
            file.transferTo(dest);
            // 生成相对路径
            String relativePath = String.format("/unit_%d/%s/%s", unitId, fileType, fileName);
            // 更新数据库中的文件路径
            CourseLearnUnit unit = unitService.getById(unitId);
            if (unit == null) {
                return Result.fail("单元不存在");
            }
            // 根据文件类型更新不同的字段
            if ("document".equals(fileType)) {
                unit.setDocPath(relativePath);
            } else if ("video".equals(fileType)) {
                unit.setVideoPath(relativePath);
            }
            // 保存更新
            boolean updated = unitService.updateById(unit);
            if (!updated) {
                return Result.fail("更新文件路径失败");
            }
            Map<String, String> data = new HashMap<>();
            data.put("filePath", relativePath);
            data.put("fileName", originalFilename);
            return Result.succ(data);

        } catch (IOException e) {
            log.error("文件上传失败", e);
            return Result.fail("文件上传失败");
        }
    }


    @GetMapping("/download/{unitId}/{fileType}/{fileName}")
    public void downloadFile(
            @PathVariable Integer unitId,
            @PathVariable String fileType,
            @PathVariable String fileName,
            HttpServletRequest request,
            HttpServletResponse response) {
        try {
            File file = new File(uploadPath + "/unit_" + unitId + "/" + fileType + "/" + fileName);
            if (!file.exists()) {
                log.error("文件不存在: {}", file.getAbsolutePath());
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                return;
            }
            // 处理视频文件
            if ("video".equals(fileType)) {
                handleVideoStream(request, response, file);
            } else {
                // 处理其他文件下载
                handleFileDownload(response, file, fileName);
            }
        } catch (IOException e) {
            log.error("文件处理失败", e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }

    private void handleVideoStream(HttpServletRequest request, HttpServletResponse response, File file) throws IOException {
        long fileLength = file.length();
        String range = request.getHeader("Range");

        // 设置响应头
        response.setHeader("Accept-Ranges", "bytes");
        response.setContentType("video/mp4");
        response.setHeader("Cache-Control", "no-cache");

        log.info("处理视频请求: {}, 文件大小: {}, Range: {}", file.getName(), fileLength, range);

        if (range != null) {
            String[] ranges = range.replace("bytes=", "").split("-");
            long start = Long.parseLong(ranges[0]);
            long end = ranges.length > 1 ? Long.parseLong(ranges[1]) : fileLength - 1;

            response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
            response.setHeader("Content-Range", String.format("bytes %d-%d/%d", start, end, fileLength));
            response.setHeader("Content-Length", String.valueOf(end - start + 1));

            log.info("断点续传: start={}, end={}", start, end);

            try (RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r")) {
                randomAccessFile.seek(start);
                byte[] buffer = new byte[8192];
                long remaining = end - start + 1;
                int len;

                while (remaining > 0 && (len = randomAccessFile.read(buffer, 0, (int) Math.min(buffer.length, remaining))) != -1) {
                    response.getOutputStream().write(buffer, 0, len);
                    remaining -= len;
                }
                response.getOutputStream().flush();
            }
        } else {
            response.setHeader("Content-Length", String.valueOf(fileLength));
            log.info("完整视频传输开始");

            try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
                 BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream())) {
                byte[] buffer = new byte[8192];
                int len;
                while ((len = bis.read(buffer)) != -1) {
                    bos.write(buffer, 0, len);
                }
                bos.flush();
            }
            log.info("完整视频传输完成");
        }
    }

    private void handleFileDownload(HttpServletResponse response, File file, String fileName) throws IOException {
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment; filename=" +
                URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()));
        response.setHeader("Content-Length", String.valueOf(file.length()));

        try (FileInputStream fis = new FileInputStream(file)) {
            IOUtils.copy(fis, response.getOutputStream());
        }
    }
  /*  @GetMapping("/download/{unitId}/{fileType}/{fileName}")
    public void downloadFile(
            @PathVariable Integer unitId,
            @PathVariable String fileType,
            @PathVariable String fileName,
            HttpServletResponse response) {
        try {
            File file = new File(uploadPath + "/unit_" + unitId + "/" + fileType + "/" + fileName);
            if (!file.exists()) {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                return;
            }

            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=" +
                    URLEncoder.encode(fileName, "UTF-8"));

            try (FileInputStream fis = new FileInputStream(file);
                 OutputStream os = response.getOutputStream()) {
                byte[] buffer = new byte[1024];
                int len;
                while ((len = fis.read(buffer)) != -1) {
                    os.write(buffer, 0, len);
                }
                os.flush();
            }
        } catch (IOException e) {
            log.error("文件下载失败", e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }*/
}